package com.leoman.service.impl;

import com.leoman.controller.common.CommonController;
import com.leoman.core.Constant;
import com.leoman.dao.*;
import com.leoman.entity.*;
import com.leoman.entity.vo.CodeVo;
import com.leoman.entity.vo.DataVo;
import com.leoman.entity.vo.StatUserData;
import com.leoman.entity.vo.VideoResumeVo;
import com.leoman.exception.*;
import com.leoman.service.AppUserService;
import com.leoman.service.RecordInfoService;
import com.leoman.utils.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import javax.persistence.Transient;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 用户接口实现
 * Created by 涂奕恒 on 2016/10/18.
 */
@Service
public class AppUserServiceImpl implements AppUserService {

    public List<CodeVo> voList = new ArrayList<>();

    @Autowired
    private CompanyUserDao companyUserDao;

    @Autowired
    private AppUserDao appUserDao;

    @Autowired
    private AppUserGainDao appUserGainDao;

    @Autowired
    private UserResumeDao userResumeDao;

    @Autowired
    private ResumeImageDao resumeImageDao;

    @Autowired
    private VideoRecordDao videoRecordDao;

    @Autowired
    private VideoResumeDao videoResumeDao;

    @Autowired
    private FeedBackDao feedBackDao;

    @Autowired
    private VideoDao videoDao;

    @Autowired
    private RecordInfoService recordInfoService;

    @Override
    public List<AppUser> findAll() {
        return appUserDao.findAll();
    }

    @Override
    public Page<AppUser> find(int pageNum, int pageSize) {
        return appUserDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<AppUser> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public AppUser getById(int id) {
        return appUserDao.findOne(id);
    }

    @Override
    public void deleteById(int id) {
        appUserDao.delete(id);
    }

    @Override
    public AppUser create(AppUser appUser) {
        return appUserDao.save(appUser);
    }

    @Override
    public AppUser update(AppUser appUser) {
        return appUserDao.save(appUser);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public String sendCode(String mobile, Integer type, Integer isCompany) throws ParamErrorException, MobileExistException, MobileNotFindException {
        if (StringUtils.isBlank(mobile)) {
            throw new ParamErrorException();
        }

        AppUser appUser = null;
        CompanyUser companyUser = null;

        // 1=注册，2=忘记密码，3=绑定手机号，默认为注册
        if (null == type) {
            type = 1;
        }
        if (null == isCompany || isCompany == 0) {
            isCompany = 0;
            appUser = appUserDao.findOneByMobile(mobile);
        } else {
            companyUser = companyUserDao.findOneByMobile(mobile);
        }

        switch (type) {
            case 1:
            case 3:
                if (isCompany == 0) {
                    if (null != appUser) {
                        throw new MobileExistException();
                    }
                } else {
                    if (null != companyUser) {
                        throw new MobileExistException();
                    }
                }
                break;
            case 2:
                if (isCompany == 0) {
                    if (null == appUser) {
                        throw new MobileNotFindException();
                    }
                } else {
                    if (null == companyUser) {
                        throw new MobileNotFindException();
                    }
                }
                break;
        }

        // 生成验证码
        String code = RandomUtil.getCode();

        // 发送验证码
        SendSMSDemo.sendMessage(mobile, code);

        removeCode(mobile, type, isCompany);

        // 将生成的验证码保存到voList中
        CodeVo codeVo = new CodeVo();
        codeVo.setMobile(mobile);
        codeVo.setCode(code);
        codeVo.setType(type);
        codeVo.setIsCompany(isCompany);
        codeVo.setCreateTime(new Date());

        voList.add(codeVo);

        return code;
    }

    @Override
    @Transactional
    public void iRegister(String mobile,
                          String password,
                          String code,
                          Integer isCompany) throws ParamErrorException, MobileExistException, CodeErrorException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        // 检测验证码是否正确
        if (!checkCode(mobile, code, 1, isCompany).equals(0)) {
            throw new CodeErrorException();
        }

        // 默认为普通用户注册
        if (null == isCompany || isCompany == 0) {
            AppUser appUser = appUserDao.findOneByMobile(mobile);

            if (null != appUser) {
                throw new MobileExistException();
            }

            appUser = new AppUser();
            appUser.setMobile(mobile);
            appUser.setPassword(Md5Util.md5(password));
            appUser.setSealStatus(Constant.APP_USER_STATUS_DEFAULT);
            appUser.setCreateTime(System.currentTimeMillis());

            appUserDao.save(appUser);
        } else {
            CompanyUser companyUser = companyUserDao.findOneByMobile(mobile);

            if (null != companyUser) {
                throw new MobileExistException();
            }

            companyUser = new CompanyUser();
            companyUser.setMobile(mobile);
            companyUser.setPassword(Md5Util.md5(password));
            companyUser.setSealStatus(Constant.APP_USER_STATUS_DEFAULT);
            companyUser.setCreateTime(System.currentTimeMillis());

            companyUserDao.save(companyUser);
        }

        // 用户增长量加一
        recordInfoService.dataGrowWithDate(null, 0, 1);

        removeCode(mobile, 1, isCompany);
    }

    @Override
    public AppUser iAppUserLogin(String mobile, String password) throws ParamErrorException, MobileNotFindException, PasswordErrorException, UserSealStatusException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password)) {
            throw new ParamErrorException();
        }

        AppUser appUser = appUserDao.findOneByMobile(mobile);

        if (null == appUser) {
            throw new MobileNotFindException();
        }

        if (!appUser.getPassword().equals(Md5Util.md5(password))) {
            throw new PasswordErrorException();
        }

        if (appUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        if (null != appUser.getRegion()) {
            appUser.setRegionId(appUser.getRegion().getId());
        }

        return appUser;
    }

    @Override
    public CompanyUser iCompanyUserLogin(String mobile, String password) throws ParamErrorException, MobileNotFindException, PasswordErrorException, UserSealStatusException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password)) {
            throw new ParamErrorException();
        }

        CompanyUser companyUser = companyUserDao.findOneByMobile(mobile);

        if (null == companyUser) {
            throw new MobileNotFindException();
        }

        if (!companyUser.getPassword().equals(Md5Util.md5(password))) {
            throw new PasswordErrorException();
        }

        if (companyUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        return companyUser;
    }

    @Override
    public Integer checkCode(String mobile, String code, Integer type, Integer isCompany) {
        if (null == type) {
            type = 1;
        }
        if (null == isCompany) {
            isCompany = 0;
        }
        Boolean flag = false;
        Integer result = 0;

        try {
            // 检查验证码是否正确，如果不正确，返回错误码
            CodeVo tempCodeVo = null;
            for (CodeVo codeVo : voList) {
                if (codeVo.getCode().equals(code) && codeVo.getMobile().equals(mobile) && codeVo.getIsCompany().equals(isCompany)) {
                    flag = true;
                    tempCodeVo = codeVo;
                }
            }

            // 1=验证码不正确 2=验证码类型不正确 3=验证码超时
            if (!flag) {
                return 1;
            } else if (!tempCodeVo.getType().equals(type)) {
                return 2;
            } else if (DateUtils.secondCompare(tempCodeVo.getCreateTime(), 600)) {
                return 3;
            } else if (!tempCodeVo.getIsCompany().equals(isCompany)) {
                return 4;
            }

            result = 0;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    public AppUser iLoginPlus(String openId,
                              Integer type,
                              String avatar,
                              String nickName) throws ParamErrorException, ThirdTypeErrorException, UserSealStatusException {
        if (StringUtils.isBlank(openId) || null == type) {
            throw new ParamErrorException();
        }
        AppUser appUser = appUserDao.findOneByOpenId(openId);

        if (null != appUser && !appUser.getType().equals(type)) {
            throw new ThirdTypeErrorException();
        }

        if (null == appUser) {
            appUser = new AppUser();
            appUser.setType(type);
            appUser.setOpenId(openId);
            appUser.setAvatar(avatar);
            appUser.setNickName(nickName);
            appUser.setSealStatus(Constant.APP_USER_STATUS_DEFAULT);
            appUser.setCreateTime(System.currentTimeMillis());

            appUserDao.save(appUser);

            // 用户增长量加一
            recordInfoService.dataGrowWithDate(null, 0, 1);
        } else {
            if (StringUtils.isBlank(appUser.getAvatar())) {
                appUser.setAvatar(avatar);
            }
            if (StringUtils.isBlank(appUser.getNickName())) {
                appUser.setNickName(nickName);
            }
        }

        if (appUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        if (null != appUser.getRegion()) {
            appUser.setRegionId(appUser.getRegion().getId());
        }

        return appUser;
    }

    @Override
    public void iForgetPwd(String mobile,
                           String password,
                           String code,
                           Integer isCompany) throws ParamErrorException, MobileNotFindException, CodeErrorException, UserSealStatusException {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        if (!checkCode(mobile, code, 2, isCompany).equals(0)) {
            throw new CodeErrorException();
        }

        // 默认为普通用户忘记密码
        if (null == isCompany || isCompany == 0) {
            AppUser appUser = appUserDao.findOneByMobile(mobile);

            if (null == appUser) {
                throw new MobileNotFindException();
            }

            if (appUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
                throw new UserSealStatusException();
            }
            appUser.setPassword(Md5Util.md5(password));
            appUser.setUpdateTime(System.currentTimeMillis());

            appUserDao.save(appUser);
        } else {
            CompanyUser companyUser = companyUserDao.findOneByMobile(mobile);

            if (null == companyUser) {
                throw new MobileNotFindException();
            }

            if (companyUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
                throw new UserSealStatusException();
            }
            companyUser.setPassword(Md5Util.md5(password));
            companyUser.setUpdateTime(System.currentTimeMillis());

            companyUserDao.save(companyUser);
        }

        removeCode(mobile, 2, isCompany);
    }

    @Override
    public void iBindingMobile(Integer userId,
                               String mobile,
                               String password,
                               String code,
                               Integer isCompany) throws ParamErrorException, UserNotFindException, MobileExistException, CodeErrorException, UserSealStatusException {
        if (null == userId || StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            throw new ParamErrorException();
        }

        if (!checkCode(mobile, code, 3, isCompany).equals(0)) {
            throw new CodeErrorException();
        }

        if (null == isCompany || isCompany == 0) {
            AppUser appUser = getAppUserInfo(userId, appUserDao);

            AppUser appUserByMobile = appUserDao.findOneByMobile(mobile);

            if (null != appUserByMobile) {
                throw new MobileExistException();
            }

            appUser.setMobile(mobile);
            appUser.setPassword(password);
            appUser.setUpdateTime(System.currentTimeMillis());

            appUserDao.save(appUser);
        } else {
            CompanyUser companyUser = getCompanyUserInfo(userId, companyUserDao);

            CompanyUser companyUserByMobile = companyUserDao.findOneByMobile(mobile);

            if (null != companyUserByMobile) {
                throw new MobileExistException();
            }

            companyUser.setMobile(mobile);
            companyUser.setPassword(password);
            companyUser.setUpdateTime(System.currentTimeMillis());

            companyUserDao.save(companyUser);
        }

        removeCode(mobile, 3, isCompany);
    }

    @Override
    public AppUser iFindOneByInfo(Integer userId) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        AppUser appUser = getAppUserInfo(userId, appUserDao);

        if (null != appUser.getRegion()) {
            appUser.setRegionId(appUser.getRegion().getId());
            appUser.setRegionInfo(appUser.getRegion().getCity().getProvince().getName() + "-" + appUser.getRegion().getCity().getName() + "-" + appUser.getRegion().getName());
        }

        return appUser;
    }

    @Override
    public UserResume iFindOneByResumeInfo(Integer userId) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        getAppUserInfo(userId, appUserDao);

        UserResume userResume = userResumeDao.findOneByUserId(userId);

        if (null != userResume) {
            if (null != userResume.getRegion()) {
                userResume.setRegionId(userResume.getRegion().getId());
                userResume.setRegionInfo(userResume.getRegion().getProvince().getName() + userResume.getRegion().getName());
            }

            if (null != userResume.getCity()) {
                userResume.setCityId(userResume.getCity().getId());
                userResume.setCityInfo(userResume.getCity().getName());
            }

            userResume.setImageList(resumeImageDao.findListByUserResumeId(userResume.getId()));
        }

        return userResume;
    }

    @Override
    public void iModifyAppUserInfo(Integer userId,
                                   String nickName,
                                   Integer sex,
                                   Integer age,
                                   Integer regionId,
                                   String email) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        AppUser appUser = getAppUserInfo(userId, appUserDao);

        if (StringUtils.isNotBlank(nickName)) {
            appUser.setNickName(nickName);
        }

        if (null != sex) {
            appUser.setSex(sex);
        }

        if (null != age) {
            appUser.setAge(age);
        }

        if (null != regionId) {
            Region region = new Region();
            region.setId(regionId);
            appUser.setRegion(region);
        }

        if (StringUtils.isNotBlank(email)) {
            appUser.setEmail(email);
        }

        if (null != appUser.getRegion()) {
            appUser.setRegionId(appUser.getRegion().getId());
        }

        appUserDao.save(appUser);
    }

    @Override
    public void iModifyAppUserPassword(Integer userId,
                                       String oldPassword,
                                       String newPassword)
            throws ParamErrorException,
            OldPasswordErrorException,
            UserNotFindException,
            UserSealStatusException {
        if (StringUtils.isBlank(oldPassword) || StringUtils.isBlank(newPassword)) {
            throw new ParamErrorException();
        }

        AppUser appUser = getAppUserInfo(userId, appUserDao);

        if (!appUser.getPassword().equals(Md5Util.md5(oldPassword))) {
            throw new OldPasswordErrorException();
        }

        appUser.setPassword(Md5Util.md5(newPassword));
        appUser.setUpdateTime(System.currentTimeMillis());

        appUserDao.save(appUser);
    }

    @Override
    public void iModifyAppUserAliPayInfo(Integer userId,
                                         String aliPayName,
                                         String aliPayAccount) throws ParamErrorException, UserNotFindException, AliPayInfoExistException, UserSealStatusException {
        if (StringUtils.isBlank(aliPayName) || StringUtils.isBlank(aliPayAccount)) {
            throw new ParamErrorException();
        }

        AppUser appUser = getAppUserInfo(userId, appUserDao);

        if (StringUtils.isNotBlank(appUser.getAliPayName())) {
            throw new AliPayInfoExistException();
        }

        appUser.setAliPayName(aliPayName);
        appUser.setAliPayAccount(aliPayAccount);

        appUserDao.save(appUser);
    }

    @Override
    public void iModifyAppUserAvatar(Integer userId, MultipartRequest multipartRequest)
            throws ParamErrorException,
            UserNotFindException,
            UserSealStatusException {
        AppUser appUser = getAppUserInfo(userId, appUserDao);

        // 获取头像文件
        MultipartFile multipartFile = multipartRequest.getFile("avatar");
        if (null == multipartFile || multipartFile.getSize() == 0) {
            throw new ParamErrorException();
        }

        QiNiuUtils.delete(appUser.getAvatar());

        appUser.setAvatar(QiNiuUtils.upload(multipartFile));

        appUserDao.save(appUser);
    }

    @Override
    @Transient
    public void iApplyMoney(Integer userId, Double money)
            throws ParamErrorException,
            UserNotFindException,
            AliPayInfoNotFindException,
            MoneyShortException,
            UserSealStatusException {
        // 提现金额最低为10元
        if (null == money || money <= 10) {
            throw new ParamErrorException();
        }

        AppUser appUser = getAppUserInfo(userId, appUserDao);

        if (StringUtils.isBlank(appUser.getAliPayName())) {
            throw new AliPayInfoNotFindException();
        }

        if (appUser.getMoney() < money) {
            throw new MoneyShortException();
        }

        // 修改该用户账户余额
        appUser.setMoney(appUser.getMoney() - money);
        appUserDao.save(appUser);

        // 新增提现记录
        AppUserGain appUserGain = new AppUserGain();
        appUserGain.setAppUser(appUser);
        appUserGain.setContent("提现");
        appUserGain.setMoney(money);
        appUserGain.setRequestStatus(Constant.GIVE_MONEY_STATUS_NO);
        appUserGain.setCreateTime(System.currentTimeMillis());

        appUserGainDao.save(appUserGain);
    }

    @Override
    public void iModifyResumeInfo(Integer userId,
                                  String userName,
                                  Integer age,
                                  String mobile,
                                  String email,
                                  Integer regionId,
                                  Integer cityId,
                                  String nationInfo,
                                  String schoolName,
                                  String educationInfo,
                                  String disciplineInfo,
                                  String situationInfo,
                                  String honorInfo,
                                  String skillInfo) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        AppUser appUser = getAppUserInfo(userId, appUserDao);

        UserResume userResume = userResumeDao.findOneByUserId(userId);

        if (null == userResume) {
            userResume = new UserResume();
            userResume.setAppUser(appUser);
            userResume.setCreateTime(System.currentTimeMillis());
        } else {
            userResume.setUpdateTime(System.currentTimeMillis());
        }

        if (StringUtils.isNotBlank(userName)) {
            userResume.setUserName(userName);
        }

        if (null != age) {
            userResume.setAge(age);
        }

        if (StringUtils.isNotBlank(mobile)) {
            userResume.setMobile(mobile);
        }

        if (StringUtils.isNotBlank(email)) {
            userResume.setEmail(email);
        }

        if (null != regionId) {
            City region = new City();
            region.setId(regionId);
            userResume.setRegion(region);
        }

        if (null != cityId) {
            City city = new City();
            city.setId(cityId);
            userResume.setCity(city);
        }

        if (StringUtils.isNotBlank(nationInfo)) {
            userResume.setNationInfo(nationInfo);
        }

        if (StringUtils.isNotBlank(schoolName)) {
            userResume.setSchoolName(schoolName);
        }

        if (StringUtils.isNotBlank(educationInfo)) {
            userResume.setEducationInfo(educationInfo);
        }

        if (StringUtils.isNotBlank(disciplineInfo)) {
            userResume.setDisciplineInfo(disciplineInfo);
        }

        if (StringUtils.isNotBlank(situationInfo)) {
            userResume.setSituationInfo(situationInfo);
        }

        if (StringUtils.isNotBlank(honorInfo)) {
            userResume.setHonorInfo(honorInfo);
        }

        if (StringUtils.isNotBlank(skillInfo)) {
            userResume.setSkillInfo(skillInfo);
        }

        userResumeDao.save(userResume);
    }

    @Override
    public void iSendResume(Integer userId, Integer videoRecordId)
            throws ParamErrorException,
            UserNotFindException,
            VideoNotFindException,
            SendResumeExistException,
            ResumeNotFindException,
            UserSealStatusException {
        getAppUserInfo(userId, appUserDao);

        if (null == videoRecordId) {
            throw new ParamErrorException();
        }

        UserResume userResume = userResumeDao.findOneByUserId(userId);

        if (null == userResume) {
            throw new ResumeNotFindException();
        }

        VideoRecord videoRecord = videoRecordDao.findOne(videoRecordId);

        if (null == videoRecord) {
            throw new VideoNotFindException();
        }

        VideoResume videoResume = videoResumeDao.iFindOneByUserIdAndVideoRecordId(userId, videoRecordId);

        if (null != videoResume) {
            throw new SendResumeExistException();
        }

        videoResume = new VideoResume();
        videoResume.setUserResume(userResumeDao.findOneByUserId(userId));
        videoResume.setVideoRecord(videoRecord);
        videoResume.setCreateTime(System.currentTimeMillis());

        videoResumeDao.save(videoResume);

        // 视频简历投递数加1
        Video video = videoRecord.getVideo();
        video.setResumeNum(video.getResumeNum() + 1);
        videoDao.save(video);
    }

    @Override
    public Page<VideoResumeVo> iPageVideoResumeForApp(final Integer userId, Integer pageNum, Integer pageSize)
            throws ParamErrorException, UserNotFindException, UserSealStatusException {
        AppUserServiceImpl.getAppUserInfo(userId, appUserDao);
        Integer[] info = CommonController.getPageParams(pageNum, pageSize);
        final Page<VideoResume> videoResumePage = videoResumeDao.iPageByUserId(userId, new PageRequest(info[0] - 1, info[1]));
        return new Page<VideoResumeVo>() {
            @Override
            public int getNumber() {
                return videoResumePage.getNumber();
            }

            @Override
            public int getSize() {
                return videoResumePage.getSize();
            }

            @Override
            public int getTotalPages() {
                return videoResumePage.getTotalPages();
            }

            @Override
            public int getNumberOfElements() {
                return videoResumePage.getNumberOfElements();
            }

            @Override
            public long getTotalElements() {
                return videoResumePage.getTotalElements();
            }

            @Override
            public boolean hasPreviousPage() {
                return videoResumePage.hasPreviousPage();
            }

            @Override
            public boolean isFirstPage() {
                return videoResumePage.isFirstPage();
            }

            @Override
            public boolean hasNextPage() {
                return videoResumePage.hasNextPage();
            }

            @Override
            public boolean isLastPage() {
                return videoResumePage.isLastPage();
            }

            @Override
            public Pageable nextPageable() {
                return videoResumePage.nextPageable();
            }

            @Override
            public Pageable previousPageable() {
                return videoResumePage.previousPageable();
            }

            @Override
            public Iterator<VideoResumeVo> iterator() {
                final Iterator<VideoResume> videoResumeIterator = videoResumePage.iterator();
                return new Iterator<VideoResumeVo>() {
                    @Override
                    public boolean hasNext() {
                        return videoResumeIterator.hasNext();
                    }

                    @Override
                    public VideoResumeVo next() {
                        return changeVideoResumeToVideoResumeVo(videoResumeIterator.next(), userId);
                    }
                };
            }

            @Override
            public List<VideoResumeVo> getContent() {
                List<VideoResume> videoResumeList = videoResumePage.getContent();
                List<VideoResumeVo> list = new ArrayList<>();

                for (VideoResume videoResume : videoResumeList) {
                    list.add(changeVideoResumeToVideoResumeVo(videoResume, userId));
                }

                return list;
            }

            @Override
            public boolean hasContent() {
                return videoResumePage.hasContent();
            }

            @Override
            public Sort getSort() {
                return videoResumePage.getSort();
            }
        };
    }

    @Override
    public void iAddFeedBack(Integer userId, String mobile, String content, Integer isCompany)
            throws ParamErrorException,
            UserNotFindException,
            MobileNotFindException,
            UserSealStatusException {
        AppUser appUser = null;
        CompanyUser companyUser = null;

        if (null == isCompany || isCompany == 0) {
            appUser = getAppUserInfo(userId, appUserDao);

            if (StringUtils.isBlank(mobile) && StringUtils.isBlank(appUser.getMobile())) {
                throw new MobileNotFindException();
            }
        } else {
            companyUser = getCompanyUserInfo(userId, companyUserDao);

            if (StringUtils.isBlank(mobile) && StringUtils.isBlank(companyUser.getMobile())) {
                throw new MobileNotFindException();
            }
        }

        FeedBack feedBack = new FeedBack();
        feedBack.setSendUserId(userId);
        if (null == isCompany || isCompany == 0) {
            feedBack.setSendType(1);
            feedBack.setMobile(StringUtils.isBlank(mobile) ? appUser.getMobile() : mobile);
        } else {
            feedBack.setSendType(2);
            feedBack.setMobile(StringUtils.isBlank(mobile) ? companyUser.getMobile() : mobile);
        }
        feedBack.setContent(content);
        feedBack.setCheckStatus(Constant.CHECK_STATUS_DEFAULT);
        feedBack.setCreateTime(System.currentTimeMillis());

        feedBackDao.save(feedBack);
    }

    @Override
    @Transactional
    public void iModifyResumeImg(Integer userId,
                                 String deleteIds,
                                 Integer imgNum,
                                 MultipartRequest multipartRequest)
            throws ParamErrorException, UserNotFindException, UserSealStatusException, ResumeNotFindException {
        List<String> list = new ArrayList<>();
        ResumeImage resumeImage;

        getAppUserInfo(userId, appUserDao);

        UserResume userResume = userResumeDao.findOneByUserId(userId);

        if (null == userResume) {
            throw new ResumeNotFindException();
        }

        // 删除证书
        if (StringUtils.isNotBlank(deleteIds)) {
            String[] ids = deleteIds.split(",");
            for (String id : ids) {
                if (StringUtils.isBlank(id)) {
                    continue;
                }
                resumeImage = resumeImageDao.findOne(Integer.parseInt(id));
                list.add(resumeImage.getUrl());
                resumeImageDao.delete(resumeImage);
            }

            // 删除七牛服务器上对应的证书图片
            for (String url : list) {
                QiNiuUtils.delete(url);
            }
        }

        // 保存简历图片信息
        List<MultipartFile> imgList = new ArrayList<>();

        if (null != imgNum) {
            MultipartFile multipartFile;
            for (int i = 0; i < imgNum; i++) {
                multipartFile = multipartRequest.getFile("image" + i);
                imgList.add(multipartFile);
            }
        } else {
            imgList = multipartRequest.getFiles("image");
        }

        for (MultipartFile file : imgList) {
            if (null != file && file.getSize() > 0) {
                resumeImage = new ResumeImage();
                resumeImage.setUserResume(userResume);
                resumeImage.setUrl(QiNiuUtils.upload(file));

                resumeImageDao.save(resumeImage);
            }
        }
    }

    @Override
    public void iModifyResumeAvatar(Integer userId, MultipartRequest multipartRequest) throws ParamErrorException, UserNotFindException, UserSealStatusException, ResumeNotFindException {
        getAppUserInfo(userId, appUserDao);

        UserResume userResume = userResumeDao.findOneByUserId(userId);

        if (null == userResume) {
            throw new ResumeNotFindException();
        }

        MultipartFile avatar = multipartRequest.getFile("avatar");

        if (null != avatar && avatar.getSize() > 0) {
            QiNiuUtils.delete(userResume.getAvatar());
            userResume.setAvatar(QiNiuUtils.upload(avatar));
        }

        userResumeDao.save(userResume);
    }

    @Override
    public Integer findCountWithNewAppUser(Integer index) {
        return appUserDao.findListByCreateTime(CommonController.getFirstTime(index)).size();
    }

    @Override
    public Integer findNewAppUserGainCount(Integer index) {
        return appUserGainDao.findListNotGainByCreateTime(CommonController.getFirstTime(index)).size();
    }

    @Override
    public Page<AppUser> pageByParams(final String mobile,
                                      final String nickName,
                                      final Integer sex,
                                      final Integer status,
                                      final Integer provinceId,
                                      final Integer cityId,
                                      Integer pageNum,
                                      Integer pageSize) {
        return appUserDao.findAll(new Specification<AppUser>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<AppUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();
                if (StringUtils.isNotBlank(mobile)) {
                    Predicate pre = cb.like(root.get("mobile").as(String.class), "%" + mobile + "%");
                    predicateList.add(pre);
                }
                if (StringUtils.isNotBlank(nickName)) {
                    Predicate pre = cb.like(root.get("nickName").as(String.class), "%" + nickName + "%");
                    predicateList.add(pre);
                }
                if (null != sex) {
                    Predicate pre = cb.equal(root.get("sex").as(Integer.class), sex);
                    predicateList.add(pre);
                }
                if (null != status) {
                    Predicate pre = cb.equal(root.get("sealStatus").as(Integer.class), status);
                    predicateList.add(pre);
                }
                if (null != provinceId || null != cityId) {
                    // 当省份id和城市id不为空时，默认查询有区域数据的用户信息
                    Predicate pre1 = cb.isNotNull(root.get("region").as(Region.class));
                    predicateList.add(pre1);

                    if (null != provinceId) {
                        Predicate pre2 = cb.equal(root.get("region").get("city").get("province").get("id").as(Integer.class), provinceId);
                        predicateList.add(pre2);
                    }

                    if (null != cityId) {
                        Predicate pre3 = cb.equal(root.get("region").get("city").get("id").as(Integer.class), cityId);
                        predicateList.add(pre3);
                    }
                }
                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    @Transient
    public Integer changeAppUserStatus(Integer[] appUserIds, Integer status) {
        try {
            AppUser appUser;
            for (Integer appUserId : appUserIds) {
                appUser = appUserDao.findOne(appUserId);
                appUser.setSealStatus(status);

                appUserDao.save(appUser);
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public StatUserData getStatUserData(Integer companyUserId) {
        // 暂定需要搜索的省份为前六名
        Integer provinceFlag = 6;
        // 暂定需要搜索的城市为前六名
        Integer cityFlag = 6;

        StatUserData statUserData = new StatUserData();
        DataVo dataVo;

        try {
            Integer allAppUserCount = null == companyUserId ? appUserDao.findAll().size() : appUserDao.findListByCompanyUserId(companyUserId).size();
            Integer maleCount = null == companyUserId ? appUserDao.findListBySex(Constant.SEX_MALE).size() : appUserDao.findListBySexAndCompanyUserId(Constant.SEX_MALE, companyUserId).size();
            Integer feMaleCount = null == companyUserId ? appUserDao.findListBySex(Constant.SEX_FEMALE).size() : appUserDao.findListBySexAndCompanyUserId(Constant.SEX_FEMALE, companyUserId).size();
            Integer nowYear = DateUtils.getYear(new Date());

            // 获取男性所占百分比
            dataVo = new DataVo();
            dataVo.setName("男");
            dataVo.setContent(getNum(maleCount, allAppUserCount));
            statUserData.getSexList().add(dataVo);

            // 获取女性所占百分比
            dataVo = new DataVo();
            dataVo.setName("女");
            dataVo.setContent(getNum(feMaleCount, allAppUserCount));
            statUserData.getSexList().add(dataVo);

            // 获取各个年龄段所占百分比
            dataVo = new DataVo();
            dataVo.setName("95后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1995).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1995, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            dataVo = new DataVo();
            dataVo.setName("90后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1995, nowYear - 1990).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1995, nowYear - 1990, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            dataVo = new DataVo();
            dataVo.setName("85后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1990, nowYear - 1985).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1990, nowYear - 1985, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            dataVo = new DataVo();
            dataVo.setName("80后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1985, nowYear - 1980).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1985, nowYear - 1980, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            dataVo = new DataVo();
            dataVo.setName("70后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1980, nowYear - 1970).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1980, nowYear - 1970, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            dataVo = new DataVo();
            dataVo.setName("60后");
            dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByAge(nowYear - 1970, nowYear - 1960).size() : appUserDao.findListByAgeAndCompanyUserId(nowYear - 1970, nowYear - 1960, companyUserId).size(), allAppUserCount));
            statUserData.getAgeList().add(dataVo);

            // 获取排名前六的省份各自所占百分比
            List<AppUser> provinceList = null == companyUserId ? appUserDao.findProvinceListOrderByDesc() : appUserDao.findProvinceListByCompanyUserIdOrderByDesc(companyUserId);
            Integer index = provinceList.size();

            if (index >= provinceFlag) {
                index = provinceFlag;
            }

            for (int i = 0; i < index; i++) {
                dataVo = new DataVo();
                dataVo.setName(provinceList.get(i).getRegion().getCity().getProvince().getName());
                dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByProvinceId(provinceList.get(i).getRegion().getCity().getProvince().getId()).size() : appUserDao.findListByProvinceIdAndCompanyUserId(provinceList.get(i).getRegion().getCity().getProvince().getId(), companyUserId).size(), allAppUserCount));
                statUserData.getProvinceList().add(dataVo);
            }

            // 获取排名前六的城市各自所占百分比
            List<AppUser> cityList = null == companyUserId ? appUserDao.findCityListOrderByDesc() : appUserDao.findCityListByCompanyUserIdOrderByDesc(companyUserId);
            index = cityList.size();

            if (index >= cityFlag) {
                index = cityFlag;
            }

            for (int i = 0; i < index; i++) {
                dataVo = new DataVo();
                dataVo.setName(cityList.get(i).getRegion().getCity().getName());
                dataVo.setContent(getNum(null == companyUserId ? appUserDao.findListByCityId(cityList.get(i).getRegion().getCity().getId()).size() : appUserDao.findListByCityIdAndCompanyUserId(cityList.get(i).getRegion().getCity().getId(), companyUserId).size(), allAppUserCount));
                statUserData.getCityList().add(dataVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return statUserData;
    }

    public static Double getNum(int firstNum, int secondNum) {
        float num = (float) firstNum / secondNum;
        DecimalFormat df = new DecimalFormat("0.0");//格式化小数
        if(firstNum == secondNum&&firstNum == 0){
            return 0.0;
        }
        return Double.parseDouble(df.format(num)) * 100;
    }

    /**
     * 移除手机号
     *
     * @param mobile    需要移除的手机号
     * @param type      验证码类型，1=注册，2=忘记密码，3=绑定手机号
     * @param isCompany 用户类型，0=普通用户，1=企业用户
     */
    private void removeCode(String mobile, Integer type, Integer isCompany) {
        if (null == type) {
            type = 1;
        }
        if (null == isCompany) {
            isCompany = 0;
        }
        // 如果匹配到了，则移除缓存中的验证码实体信息
        Iterator iterator = voList.iterator();
        CodeVo vo;
        while (iterator.hasNext()) {
            vo = (CodeVo) iterator.next();
            if (vo.getMobile().equals(mobile) && vo.getType().equals(type) && vo.getIsCompany().equals(isCompany)) {
                iterator.remove();
            }
        }
    }

    /**
     * 获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息实体
     * @throws UserNotFindException    参数不正确异常
     * @throws UserNotFindException    找不到用户信息异常
     * @throws UserSealStatusException 用户已被禁用异常
     */
    public static AppUser getAppUserInfo(Integer userId, AppUserDao appUserDao) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        if (null == userId) {
            throw new ParamErrorException();
        }

        AppUser appUser = appUserDao.findOne(userId);

        if (null == appUser) {
            throw new UserNotFindException();
        }

        if (appUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        return appUser;
    }

    /**
     * 获取企业用户信息
     *
     * @param companyUserId 企业用户ID
     * @return 用户信息实体
     * @throws UserNotFindException    参数不正确异常
     * @throws UserNotFindException    找不到用户信息异常
     * @throws UserSealStatusException 用户已被禁用异常
     */
    public static CompanyUser getCompanyUserInfo(Integer companyUserId, CompanyUserDao companyUserDao) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        if (null == companyUserId) {
            throw new ParamErrorException();
        }

        CompanyUser companyUser = companyUserDao.findOne(companyUserId);

        if (null == companyUser) {
            throw new UserNotFindException();
        }

        if (companyUser.getSealStatus().equals(Constant.APP_USER_STATUS_DISABLED)) {
            throw new UserSealStatusException();
        }

        return companyUser;
    }

    /**
     * 将简历投递记录转换为简历投递记录Vo
     *
     * @param videoResume 简历投递记录
     * @param userId      用户ID
     * @return 简历投递记录Vo
     */
    private VideoResumeVo changeVideoResumeToVideoResumeVo(VideoResume videoResume, Integer userId) {
        VideoResumeVo videoResumeVo = new VideoResumeVo();

        videoResumeVo.setVideoId(videoResume.getVideoRecord().getId());
        videoResumeVo.setVideoCover(videoResume.getVideoRecord().getVideo().getCover());
        videoResumeVo.setVideoName(videoResume.getVideoRecord().getVideo().getName());
        videoResumeVo.setTypeName(videoResume.getVideoRecord().getVideo().getVideoType().getName());
        videoResumeVo.setVideoDuration(videoResume.getVideoRecord().getVideo().getDuration());
        videoResumeVo.setPrice(videoResume.getVideoRecord().getPrice());
        videoResumeVo.setIsGet((null == userId || null == videoResume.getVideoRecord() || appUserGainDao.iFindListByVideoRecordIdAndUserId(videoResume.getVideoRecord().getId(), userId).size() == 0) ? 0 : 1);
        videoResumeVo.setCreateTime(videoResume.getCreateTime());

        return videoResumeVo;
    }
}